package model

import (
	"encoding/json"
	"time"

	"dev.ixmxm.top/rms/proto"
)

//货叉动作类型
type ForkActionType uint8

const (
	ForkNone            ForkActionType = 0 // 无控制
	ForkHeight          ForkActionType = 1 // 货叉高度移动(层高)
	ForkSide            ForkActionType = 2 // 货叉侧移(方向)
	ForkRotate          ForkActionType = 3 // 货叉旋转(指定值)
	ForkTranslate       ForkActionType = 4 // 货叉前后移动(指定值)
	ForkSpace           ForkActionType = 5 // 货叉间距变化()
	ForkLead            ForkActionType = 6 // 倾仰(取放货)
	ForkSiwtchDirection ForkActionType = 7 // 货叉换向（货叉旋转和侧移）(方向和点位)
)

//子任务
type Subtask struct {
	Id                   uint64              `json:"id" bson:"id"`                                                                //主键
	TaskId               uint64              `json:"task_id" bson:"task_id"`                                                      //任务Id
	Index                int                 `json:"index" bson:"index"`                                                          //子任务索引
	Type                 TaskType            `json:"task_type" bson:"type" binding:"required,oneof=1 2 3 4 5"`                    //任务类型
	Status               TaskStatus          `json:"status" bson:"status"`                                                        //任务状态
	MapName              string              `json:"map_name" binding:"required" bson:"map_name"`                                 //厂区
	AgvId                string              `json:"agv_id" bson:"agv_id"`                                                        //小车编号
	MainTaskTargetSiteID string              `json:"main_task_target_site_id" binding:"required" bson:"main_task_target_site_id"` //RMS主任务目标点
	MainTaskCode         string              `json:"main_task_code" binding:"required" bson:"main_task_code"`                     //中间件主任务编号
	TargetSiteID         string              `json:"target_site_id" binding:"required" bson:"target_site_id"`                     //目标点点位ID
	TargetLayer          int32               `json:"target_layer" bson:"target_layer"`                                            //目标点点位层级
	TargetDirection      int32               `json:"target_direction" bson:"target_direction"`                                    //目标方向
	ForkActions          ForkActions         `json:"fork_actions" bson:"fork_actions"`                                            //货叉指令集合（仅货叉任务使用）
	CompleteProcessType  int                 `json:"complete_process_type" bson:"complete_process_type"`                          //执行完成处理类型 0=不执行
	CompleteProcessValue string              `json:"complete_process_value" bson:"complete_process_value"`                        //执行完成处理类型 0=不执行
	IsCompleteProcess    int                 `json:"is_complete_process" bson:"is_complete_process"`                              //是否已经执行任务完成处理 0=未执行、1=已执行
	AdditiveInfo         string              `json:"additive_info" bson:"additive_info"`                                          //附加信息
	CreatedTime          time.Time           `json:"created_time" bson:"created_time"`                                            //创建时间
	StartTime            time.Time           `json:"start_time,omitempty" bson:"start_time"`                                      //开始时间
	FinishTime           time.Time           `json:"finish_time,omitempty" bson:"finish_time"`                                    //结束时间
	WalkType             int32               `json:"walk_type" bson:"walk_type"`                                                  //任务类型：0=行走高度、1=放货高度、2=取货高度
	Grade                int                 `json:"grade" bson:"grade"`                                                          //任务的优先级
	PalletDetection      PalletDetectionType `json:"pallet_detection" bson:"pallet_detection"`                                    //货物检测：0=不检测、1=空托检测、2=满托检测、3=检测
	SubStatus            TaskSubStatus       `json:"sub_status" bson:"sub_status"`                                                //任务的子状态
	TempTargetSite       string              `json:"temp_target_site" bson:"temp_target_site"`                                    //临时目标点
	AvoidSite            string              `json:"avoid_site" bson:"avoid_site"`                                                //避让点
	TargetLayerCopy      int32               `json:"-" bson:"target_layer_copy"`                                                  //目标层数备份
	WalkTypeCopy         int32               `json:"walk_type_copy" bson:"walk_type_copy"`                                        //任务类型备份：0=行走高度、1=放货高度、2=取货高度
	BlockAgv             string              `json:"block_agv" bson:"block_agv"`                                                  //堵塞的agv
	Paths                TrafficPaths        `json:"-" bson:"paths"`
	BlockAgvSite         string              `json:"-" bson:"block_agv_site"`              //堵塞的agv站点
	BlockTask            uint64              `json:"-" bson:"block_task"`                  //堵塞的agv的任务
	BlockTaskGrade       int                 `json:"-" bson:"block_task_grade"`            //堵塞的agv的任务的优先级
	BlockStartTime       time.Time           `json:"-" bson:"block_start_time"`            //堵塞开始时间
	BlockAvoidTime       time.Time           `json:"-" bson:"block_avoid_time"`            //上次堵塞避让结束时间
	ExternalGrade        int                 `json:"-" bson:"external_grade"`              //额外计算的优先级
	RetryCount           int                 `json:"-" bson:"retry_count"`                 //重新计算次数统计
	NextSwitchType       MapRelationType     `json:"-" bson:"next_switch_type"`            //记录下个任务切换地图类别
	NextSwitchDevice     string              `json:"-" bson:"next_switch_device"`          //记录下个任务切换设备号
	NextSwitchDeviceCopy string              `json:"-" bson:"next_switch_device_copy"`     //记录下个任务切换设备号备份
	SwitchType           MapRelationType     `json:"-" bson:"switch_type"`                 //记录任务完成切换地图类别
	SwitchDevice         string              `json:"-" bson:"switch_device"`               //记录任务完成切换设备号
	SwitchDeviceCopy     string              `json:"-" bson:"switch_device_copy"`          //记录任务完成切换设备号备份
	SwitchFromSite       string              `json:"-" bson:"switch_from_site"`            //记录任务完成上一个点位
	SwitchFromMap        string              `json:"-" bson:"switch_from_map"`             //记录任务完成切换点位
	SwitchToSite         string              `json:"-" bson:"switch_to_site"`              //记录任务完成切换点位
	SwitchToPath         string              `json:"-" bson:"switch_to_path"`              //记录任务完成切换路径
	IsForkReport         int                 `json:"is_fork_report" bson:"is_fork_report"` //货查动作是否需要上报 1：需要 0：不需要
	CheckType            int                 `json:"check_type" bson:"check_type"`         //检测类型0:不检测 1:任务检测 2:安全检测
	TaskOperateFlg       int                 `json:"-" bson:"task_operate_flag"`
	CheckFlg             int                 `json:"-" bson:"check_flag"`                  //地堆库标记 0：不校验 1：取货校验 2：放货校验
	IsCallDevice         bool                `json:"is_call_device" bson:"is_call_device"` //任务开始请求设备（目前只限于称重平台）
}

func (subtask *Subtask) MarshalJSON() ([]byte, error) {
	type Alias Subtask
	return json.Marshal(&struct {
		*Alias
		CreatedTime    DateTime `json:"created_time"`
		StartTime      DateTime `json:"start_time"`
		FinishTime     DateTime `json:"finish_time"`
		BlockStartTime DateTime `json:"block_start_time"`
		BlockAvoidTime DateTime `json:"block_avoid_time"`
	}{
		Alias:          (*Alias)(subtask),
		CreatedTime:    DateTime(subtask.CreatedTime),
		StartTime:      DateTime(subtask.StartTime),
		FinishTime:     DateTime(subtask.FinishTime),
		BlockStartTime: DateTime(subtask.BlockStartTime),
		BlockAvoidTime: DateTime(subtask.BlockAvoidTime),
	})
}

//生成货叉命令
func (subtask *Subtask) GetForkActions(forkIndex int32) []*proto.ForkPb {
	forkActions := []*proto.ForkPb{}
	if subtask.Type == TaskTypeFork || subtask.Type == TaskTypeNaviWithFork {
		for index, forkAction := range subtask.ForkActions {
			ForkIndex := int32(index + 1)
			if ForkIndex < forkIndex {
				continue
			}
			forkPb := proto.ForkPb{
				ForkType:  int32(forkAction.ForkType),
				ForkValue: forkAction.ForkValue,
				ForkCmd:   forkAction.ForkCmd,
				ForkIndex: ForkIndex,
				Reserve:   "",
			}
			forkActions = append(forkActions, &forkPb)
		}
	}
	return forkActions
}

func (Subtask) TableName() string {
	return "t_data_subtasks"
}

//货叉指令集合（仅货叉任务使用）
type ForkActions []ForkAction

//货叉指令
type ForkAction struct {
	ForkType  ForkActionType `json:"fork_type" bson:"fork_type"`   //货叉动作类型
	ForkValue int32          `json:"fork_value" bson:"fork_value"` //货叉动作参数
	ForkCmd   int32          `json:"fork_cmd" bson:"fork_cmd"`     //高度：0=保持、1=抬升;   摇避启用:1=启用/2=关闭
	Reserve   string         `json:"reserve" bson:"reserve"`       //保留字段
}

//任务转化为子任务
func (subtask *Subtask) ConvertByTask(task Task, agvId string) {
	forkActions := []ForkAction{}
	*subtask = Subtask{
		TaskId:               task.Id,
		Index:                0,
		Type:                 task.Type,
		Status:               TaskStatusRegister,
		MapName:              task.MapName,
		TargetSiteID:         task.TargetSiteID,
		TargetLayer:          task.TargetLayer,
		TargetLayerCopy:      task.TargetLayer,
		TargetDirection:      task.TargetDirection,
		Grade:                task.Grade,
		PalletDetection:      PalletDetectionTypeNone,
		AgvId:                agvId,
		ForkActions:          forkActions,
		CompleteProcessType:  0,
		CompleteProcessValue: "",
		IsCompleteProcess:    0,
		AdditiveInfo:         task.AdditiveInfo,
		CreatedTime:          time.Now(),
		WalkType:             task.Type.GetWalkType(),
		WalkTypeCopy:         task.Type.GetWalkType(),
		MainTaskTargetSiteID: task.TargetSiteID,
		IsForkReport:         1,
		CheckType:            0,
	}
}

type TaskInfo struct {
	TaskMapName string
	TaskSiteId  string
	ToMapName   string
	ToMapSite   string
	ToMapPath   string
	DeviceCode  string
	SwitchType  MapRelationType //0=同层  1=切换厂区  2=切换楼层
}

//模板转化为子任务
func (subtask *Subtask) ConvertByTemplate(task Task, taskItemTemplate TaskItemTemplate, robot *Robot, mapName string, siteId string) {
	var walkType int32 = 0
	if (task.Type == TaskTypePick || task.Type == TaskTypePut) &&
		(taskItemTemplate.TargetType == TargetTypeTaskEnd || taskItemTemplate.TargetType == TargetTypeTaskEndFront || taskItemTemplate.TargetType == TargetTypeTaskEndFrontPoint) {
		walkType = task.Type.GetWalkType()
	}
	//称重任务类型
	if task.Type == TaskTypeWeigh {
		if taskItemTemplate.TaskType == TaskTypePick || taskItemTemplate.TaskType == TaskTypePut {
			walkType = taskItemTemplate.TaskType.GetWalkType()
		} else {
			walkType = taskItemTemplate.WalkType.GetWalkType()
		}
	} else {
		if taskItemTemplate.TargetType == TargetTypeTaskEndFrontPoint && taskItemTemplate.WalkType == WalkItemTypeRun {
			walkType = 0 //行走
		}
	}

	isCallDevice := false
	if taskItemTemplate.IsCallDevice == 1 && task.Type == TaskTypeWeigh {
		isCallDevice = true
	}
	*subtask = Subtask{
		TaskId:               task.Id,
		Index:                taskItemTemplate.Index,
		Type:                 taskItemTemplate.TaskType,
		Status:               TaskStatusRegister,
		MapName:              mapName,
		TargetSiteID:         siteId,
		TargetLayer:          task.TargetLayer,
		TargetLayerCopy:      task.TargetLayer,
		TargetDirection:      taskItemTemplate.TargetDirection,
		Grade:                task.Grade,
		PalletDetection:      taskItemTemplate.PalletDetection,
		AgvId:                robot.Account.AgvId,
		ForkActions:          ForkCmdConvert(task, taskItemTemplate, robot),
		CompleteProcessType:  int(taskItemTemplate.CompleteProcessType),
		CompleteProcessValue: "",
		IsCompleteProcess:    int(taskItemTemplate.CompleteProcessType),
		AdditiveInfo:         task.AdditiveInfo,
		CreatedTime:          time.Now(),
		WalkType:             walkType,
		WalkTypeCopy:         walkType,
		MainTaskTargetSiteID: task.TargetSiteID,
		IsForkReport:         taskItemTemplate.IsForkReport,
		CheckType:            taskItemTemplate.CheckType,
		IsCallDevice:         isCallDevice,
	}
}

//货叉命令转换
func ForkCmdConvert(task Task, taskItemTemplate TaskItemTemplate, robot *Robot) []ForkAction {
	forkActions := []ForkAction{}
	for _, forkTemplateCmd := range taskItemTemplate.ForkTemplateCmds {
		cmd := forkTemplateCmd.ForkCmd
		value := forkTemplateCmd.ForkValue

		//获取value
		switch forkTemplateCmd.ForkType {
		//cmd不变、value=0
		case ForkNone:
			value = 0
			break

		//cmd=是否抬升、value=层高
		case ForkHeight:

			cmd = forkTemplateCmd.ForkCmd
			if cmd != 3 {
				value = task.TargetLayer
			}
			break

		case ForkSide:
			//侧叉车
			//cmd=0、value=根据车型和伸出方向进行处理
			if robot.Type.CategoryType == CategoryTypeSideFork {
				//value:0=中间、1=左、2=右、3=左2、4=右2
				if forkTemplateCmd.ForkCmd == 3 {
					value = 0
				} else {
					value = taskItemTemplate.TargetDirection
				}
				cmd = 0
			}
			//三项叉
			//cmd=(1、取货伸出  2、取货缩回  3、放货伸出  4、放货缩回)
			if robot.Type.CategoryType == CategoryTypeThreeWay {
				// if forkTemplateCmd.ForkCmd == 1 {
				// 	cmd = 1
				// } else if forkTemplateCmd.ForkCmd == 4 {
				// 	cmd = 3
				// } else if forkTemplateCmd.ForkCmd == 5 || forkTemplateCmd.ForkCmd == 6 {

				// 	cmd = 4
				// } else {
				// 	cmd = 2
				// }

				if forkTemplateCmd.ForkCmd == 1 || forkTemplateCmd.ForkCmd == 3 {
					value = taskItemTemplate.TargetDirection
				}
				if forkTemplateCmd.ForkCmd == 2 || forkTemplateCmd.ForkCmd == 4 {
					if taskItemTemplate.TargetDirection == 1 {
						value = 2
					} else if taskItemTemplate.TargetDirection == 2 {
						value = 1
					} else if taskItemTemplate.TargetDirection == 3 {
						value = 2
					} else if taskItemTemplate.TargetDirection == 4 {
						value = 1
					}
				}
			}
			break

		//无车型
		//cmd不变、value=0
		case ForkRotate:
			value = 0
			break

		//cmd=是否启用摇臂、value=伸出或缩回 //cmd=(1、取货伸出  2、取货缩回  3、放货伸出  4、放货缩回)
		case ForkTranslate:
			if robot.Type.CategoryType == CategoryTypeFronted || robot.Type.CategoryType == CategoryTypeClamp {
				// if forkTemplateCmd.ForkCmd == 1 {
				// 	cmd = 1
				// } else {
				// 	cmd = 2
				// }

				if forkTemplateCmd.ForkCmd == 2 || forkTemplateCmd.ForkCmd == 4 {
					value = 0
				} else if forkTemplateCmd.ForkCmd == 1 || forkTemplateCmd.ForkCmd == 3 {
					value = 1
				}
			}
			break

		case ForkSpace:
			value = forkTemplateCmd.ForkCmd
			break
		case ForkLead:
			value = forkTemplateCmd.ForkCmd
			break

		//三向叉 cmd=是否启用摇臂、value=方向
		case ForkSiwtchDirection:
			if robot.Type.CategoryType == CategoryTypeThreeWay {
				if forkTemplateCmd.ForkCmd == 1 {
					cmd = 1
				} else {
					cmd = 2
				}

				value = taskItemTemplate.TargetDirection
			}
			break
		}

		forkAction := ForkAction{
			ForkType:  forkTemplateCmd.ForkType,
			ForkValue: value,
			ForkCmd:   cmd,
		}
		forkActions = append(forkActions, forkAction)
	}
	return forkActions
}
